1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package sun.security.util;
27
28 import java.io.ByteArrayOutputStream;
29 import java.io.OutputStream;
30 import java.io.IOException;
31 import java.text.SimpleDateFormat;
32 import java.util.Date;
33 import java.util.TimeZone;
34 import java.util.Comparator;
35 import java.util.Arrays;
36 import java.math.BigInteger;
37 import java.util.Locale;
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 public class DerOutputStream
55 extends ByteArrayOutputStream implements DerEncoder {
56
57
58
59
60
61 public DerOutputStream(int size) { super(size); }
62
63
64
65
66 public DerOutputStream() { }
67
68
69
70
71
72
73
74
75
76
77 public void write(byte tag, byte[] buf) throws IOException {
78 write(tag);
79 putLength(buf.length);
80 write(buf, 0, buf.length);
81 }
82
83
84
85
86
87
88
89
90
91
92 public void write(byte tag, DerOutputStream out) throws IOException {
93 write(tag);
94 putLength(out.count);
95 write(out.buf, 0, out.count);
96 }
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115 public void writeImplicit(byte tag, DerOutputStream value)
116 throws IOException {
117 write(tag);
118 write(value.buf, 1, value.count-1);
119 }
120
121
122
123
124 public void putDerValue(DerValue val) throws IOException {
125 val.encode(this);
126 }
127
128
129
130
131
132
133
134
135
136
137
138
139 public void putBoolean(boolean val) throws IOException {
140 write(DerValue.tag_Boolean);
141 putLength(1);
142 if (val) {
143 write(0xff);
144 } else {
145 write(0);
146 }
147 }
148
149
150
151
152
153 public void putEnumerated(int i) throws IOException {
154 write(DerValue.tag_Enumerated);
155 putIntegerContents(i);
156 }
157
158
159
160
161
162
163 public void putInteger(BigInteger i) throws IOException {
164 write(DerValue.tag_Integer);
165 byte[] buf = i.toByteArray();
166 putLength(buf.length);
167 write(buf, 0, buf.length);
168 }
169
170
171
172
173
174 public void putInteger(Integer i) throws IOException {
175 putInteger(i.intValue());
176 }
177
178
179
180
181
182 public void putInteger(int i) throws IOException {
183 write(DerValue.tag_Integer);
184 putIntegerContents(i);
185 }
186
187 private void putIntegerContents(int i) throws IOException {
188
189 byte[] bytes = new byte[4];
190 int start = 0;
191
192
193
194 bytes[3] = (byte) (i & 0xff);
195 bytes[2] = (byte)((i & 0xff00) >>> 8);
196 bytes[1] = (byte)((i & 0xff0000) >>> 16);
197 bytes[0] = (byte)((i & 0xff000000) >>> 24);
198
199
200
201
202 if (bytes[0] == (byte)0xff) {
203
204
205
206 for (int j = 0; j < 3; j++) {
207 if ((bytes[j] == (byte)0xff) &&
208 ((bytes[j+1] & 0x80) == 0x80))
209 start++;
210 else
211 break;
212 }
213 } else if (bytes[0] == 0x00) {
214
215
216
217 for (int j = 0; j < 3; j++) {
218 if ((bytes[j] == 0x00) &&
219 ((bytes[j+1] & 0x80) == 0))
220 start++;
221 else
222 break;
223 }
224 }
225
226 putLength(4 - start);
227 for (int k = start; k < 4; k++)
228 write(bytes[k]);
229 }
230
231
232
233
234
235
236
237 public void putBitString(byte[] bits) throws IOException {
238 write(DerValue.tag_BitString);
239 putLength(bits.length + 1);
240 write(0);
241 write(bits);
242 }
243
244
245
246
247
248
249
250 public void putUnalignedBitString(BitArray ba) throws IOException {
251 byte[] bits = ba.toByteArray();
252
253 write(DerValue.tag_BitString);
254 putLength(bits.length + 1);
255 write(bits.length*8 - ba.length());
256 write(bits);
257 }
258
259
260
261
262
263
264
265 public void putTruncatedUnalignedBitString(BitArray ba) throws IOException {
266 putUnalignedBitString(ba.truncate());
267 }
268
269
270
271
272
273
274 public void putOctetString(byte[] octets) throws IOException {
275 write(DerValue.tag_OctetString, octets);
276 }
277
278
279
280
281
282 public void putNull() throws IOException {
283 write(DerValue.tag_Null);
284 putLength(0);
285 }
286
287
288
289
290
291 public void putOID(ObjectIdentifier oid) throws IOException {
292 oid.encode(this);
293 }
294
295
296
297
298
299
300 public void putSequence(DerValue[] seq) throws IOException {
301 DerOutputStream bytes = new DerOutputStream();
302 int i;
303
304 for (i = 0; i < seq.length; i++)
305 seq[i].encode(bytes);
306
307 write(DerValue.tag_Sequence, bytes);
308 }
309
310
311
312
313
314
315
316
317 public void putSet(DerValue[] set) throws IOException {
318 DerOutputStream bytes = new DerOutputStream();
319 int i;
320
321 for (i = 0; i < set.length; i++)
322 set[i].encode(bytes);
323
324 write(DerValue.tag_Set, bytes);
325 }
326
327
328
329
330
331
332
333
334
335
336
337 public void putOrderedSetOf(byte tag, DerEncoder[] set) throws IOException {
338 putOrderedSet(tag, set, lexOrder);
339 }
340
341
342
343
344
345
346
347
348
349
350
351 public void putOrderedSet(byte tag, DerEncoder[] set) throws IOException {
352 putOrderedSet(tag, set, tagOrder);
353 }
354
355
356
357
358
359 private static ByteArrayLexOrder lexOrder = new ByteArrayLexOrder();
360
361
362
363
364
365 private static ByteArrayTagOrder tagOrder = new ByteArrayTagOrder();
366
367
368
369
370
371
372
373 private void putOrderedSet(byte tag, DerEncoder[] set,
374 Comparator<byte[]> order) throws IOException {
375 DerOutputStream[] streams = new DerOutputStream[set.length];
376
377 for (int i = 0; i < set.length; i++) {
378 streams[i] = new DerOutputStream();
379 set[i].derEncode(streams[i]);
380 }
381
382
383 byte[][] bufs = new byte[streams.length][];
384 for (int i = 0; i < streams.length; i++) {
385 bufs[i] = streams[i].toByteArray();
386 }
387 Arrays.<byte[]>sort(bufs, order);
388
389 DerOutputStream bytes = new DerOutputStream();
390 for (int i = 0; i < streams.length; i++) {
391 bytes.write(bufs[i]);
392 }
393 write(tag, bytes);
394
395 }
396
397
398
399
400 public void putUTF8String(String s) throws IOException {
401 writeString(s, DerValue.tag_UTF8String, "UTF8");
402 }
403
404
405
406
407 public void putPrintableString(String s) throws IOException {
408 writeString(s, DerValue.tag_PrintableString, "ASCII");
409 }
410
411
412
413
414 public void putT61String(String s) throws IOException {
415
416
417
418
419 writeString(s, DerValue.tag_T61String, "ISO-8859-1");
420 }
421
422
423
424
425 public void putIA5String(String s) throws IOException {
426 writeString(s, DerValue.tag_IA5String, "ASCII");
427 }
428
429
430
431
432 public void putBMPString(String s) throws IOException {
433 writeString(s, DerValue.tag_BMPString, "UnicodeBigUnmarked");
434 }
435
436
437
438
439 public void putGeneralString(String s) throws IOException {
440 writeString(s, DerValue.tag_GeneralString, "ASCII");
441 }
442
443
444
445
446
447
448
449
450
451 private void writeString(String s, byte stringTag, String enc)
452 throws IOException {
453
454 byte[] data = s.getBytes(enc);
455 write(stringTag);
456 putLength(data.length);
457 write(data);
458 }
459
460
461
462
463
464
465
466 public void putUTCTime(Date d) throws IOException {
467 putTime(d, DerValue.tag_UtcTime);
468 }
469
470
471
472
473
474
475
476 public void putGeneralizedTime(Date d) throws IOException {
477 putTime(d, DerValue.tag_GeneralizedTime);
478 }
479
480
481
482
483
484
485
486
487 private void putTime(Date d, byte tag) throws IOException {
488
489
490
491
492
493 TimeZone tz = TimeZone.getTimeZone("GMT");
494 String pattern = null;
495
496 if (tag == DerValue.tag_UtcTime) {
497 pattern = "yyMMddHHmmss'Z'";
498 } else {
499 tag = DerValue.tag_GeneralizedTime;
500 pattern = "yyyyMMddHHmmss'Z'";
501 }
502
503 SimpleDateFormat sdf = new SimpleDateFormat(pattern, Locale.US);
504 sdf.setTimeZone(tz);
505 byte[] time = (sdf.format(d)).getBytes("ISO-8859-1");
506
507
508
509
510
511 write(tag);
512 putLength(time.length);
513 write(time);
514 }
515
516
517
518
519
520
521
522 public void putLength(int len) throws IOException {
523 if (len < 128) {
524 write((byte)len);
525
526 } else if (len < (1 << 8)) {
527 write((byte)0x081);
528 write((byte)len);
529
530 } else if (len < (1 << 16)) {
531 write((byte)0x082);
532 write((byte)(len >> 8));
533 write((byte)len);
534
535 } else if (len < (1 << 24)) {
536 write((byte)0x083);
537 write((byte)(len >> 16));
538 write((byte)(len >> 8));
539 write((byte)len);
540
541 } else {
542 write((byte)0x084);
543 write((byte)(len >> 24));
544 write((byte)(len >> 16));
545 write((byte)(len >> 8));
546 write((byte)len);
547 }
548 }
549
550
551
552
553
554
555
556
557
558
559 public void putTag(byte tagClass, boolean form, byte val) {
560 byte tag = (byte)(tagClass | val);
561 if (form) {
562 tag |= (byte)0x20;
563 }
564 write(tag);
565 }
566
567
568
569
570
571
572
573 public void derEncode(OutputStream out) throws IOException {
574 out.write(toByteArray());
575 }
576 }